package com.amyi.usercenter.service.impl;

import com.amyi.usercenter.common.ErrorCode;
import com.amyi.usercenter.constant.UserConstant;
import com.amyi.usercenter.domain.User;
import com.amyi.usercenter.exception.BusinessException;
import com.amyi.usercenter.mapper.UserMapper;
import com.amyi.usercenter.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 用户服务实现类
* @author 张莹莹
* @description 针对表【user(用户表)】的数据库操作Service实现
* @createDate 2023-10-09 15:38:09
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {
@Resource
private UserMapper userMapper;
    /**
     * 盐值混淆密码
     */
    public static final String SALT="amyi";

    @Override
    public long userRegister(String userAccount, String userPassword, String checkPassword,String planetCode) {

//        一、校验用户的账户、密码、校验密码，是否符合要求
//        1.非空
        if(StringUtils.isAnyBlank(userAccount,userPassword,checkPassword)){
            //isAnyBlank可以同时判断几个字符串变量是否为空或null
            log.info("三个变量不能为空或null");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"参数不能为空");
        }
        //        2.账户的话不小于4位
        if(userAccount.length()<4){
            log.info("账户不能小于四位");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账户名不能少于四位");
        }
        //        3.密码就不小于8位吧
        if(userPassword.length()<8||checkPassword.length()<8){
            log.info("密码不能小于8位");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码不能小于8位");
        }
        if(planetCode.length()>5){
            log.info("星球编号不能大于5");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"星球编号不能大于5");
        }
        //        4.账户不包含特殊字符
        //账户不能包含特殊字符
        String validPattern ="[^a-zA-Z0-9_]";
        Matcher matcher =Pattern.compile(validPattern).matcher(userAccount);
        if (matcher.find()) {
            log.info("账户中包含特殊字符");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账户中包含特殊字符");
        }
        //        5.账户不能重复
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount",userAccount);
        User user = userMapper.selectOne(queryWrapper);
        if(user!=null){
            log.info("用户名已存在");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户名已存在");
        }
        //星球编号不能重复
         queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("planetCode",planetCode);
        User u = userMapper.selectOne(queryWrapper);
        if(u!=null){
            log.info("星球编号已占用");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"星球编号已占用");
        }
//        6.密码和校验密码相同
        if(!userPassword.equals(checkPassword)){
            log.info("密码和校验密码不一致");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码和校验密码不一致");
        }
        //二、加密

       String newPassword = DigestUtils.md5DigestAsHex((SALT+ userPassword).getBytes());
       //插入数据
        User user1 = new User();
        user1.setUserAccount(userAccount);
        user1.setUserPassword(newPassword);
        user1.setPlanetCode(planetCode);
        int insert = userMapper.insert(user1);
        if(insert==0){
            log.info("插入数据失败");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"插入数据失败");
        }
        return user1.getId();
    }

    @Override
    public User login(String userAccount, String userPassword, HttpServletRequest request) {
        //1.校验
        //非空
        if(StringUtils.isAnyBlank(userAccount,userPassword)){
            log.info("请输入账户和密码");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"请输入账户和密码");
        }
        //        2.账户的话不小于4位
        if(userAccount.length()<4){
            log.info("账户不能小于四位");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账户不能小于四位");
        }
        //        3.密码就不小于8位吧
        if(userPassword.length()<8){
            log.info("密码不能小于8位");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码不能小于8位");
        }
        //账户不能包含特殊字符
        String validPattern ="[^a-zA-Z0-9_]";
        Matcher matcher =Pattern.compile(validPattern).matcher(userAccount);
        if (matcher.find()) {
            log.info("账户中包含特殊字符");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账户中包含特殊字符");
        }
        //账户存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount",userAccount);
        User user = userMapper.selectOne(queryWrapper);
        if(user==null){
            log.info("账户不存在，请注册");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账户不存在，请注册");
        }
        //账户和密码匹配
        //获取盐值和密码进行哈希运算，看看运算出来的结果是否想等判断是否登录成功
        String password = user.getUserPassword();
        //获取盐值
        //将盐值和密码进行运算之后与password比较
        String newPassword = DigestUtils.md5DigestAsHex((SALT+ userPassword).getBytes());
        if(!newPassword.equals(password)){
            log.info("账户和密码不匹配");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账户和密码不匹配");
        }
        //2.用户脱敏
        User safetyUser = safetyUser(user);
        //获取会话，并存键值对到session中
        //3.记录用户的登录态
        request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE,safetyUser);

        return safetyUser;
    }


    @Override
    public int userLogout(HttpServletRequest request) {
        //移除登录态
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
        return 1;
    }

    @Override
    public User getCurrentUser(HttpServletRequest request) {
        final Object useObject = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        User user=(User) useObject;
        if(user==null){
            return null;
        }
        Long userId=user.getId();
        final User newUser = userMapper.selectById(userId);
        return safetyUser(newUser);
    }

    @Override
    public List<User> searchUsers(String username, HttpServletRequest request) {
        if(!isAdmin(request)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        QueryWrapper<User> queryWrapper =new QueryWrapper<>();
        if (StringUtils.isNotBlank(username)) {
            queryWrapper.like("username", username);
        }
        List<User> list = userMapper.selectList(queryWrapper);
        List<User> result = list.stream().map(user -> (safetyUser(user))).collect(Collectors.toList());
        return list;
    }

    @Override
    public boolean deleteUser(long id, HttpServletRequest request) {
        if(!isAdmin(request)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        int i = userMapper.deleteById(id);
        if(i<=0)
        {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"删除失败");
        }
        return true;
    }

    private User safetyUser(User originalUser){
        if(originalUser==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户不能为空");
        }
        User safetyUser = new User();//没有给user的password赋值，查询到的就是空密码
        safetyUser.setId(originalUser.getId());
        safetyUser.setUsername(originalUser.getUsername());
        safetyUser.setUserAccount(originalUser.getUserAccount());
        safetyUser.setAvatarUrl(originalUser.getAvatarUrl());
        safetyUser.setGender(originalUser.getGender());
        safetyUser.setEmail(originalUser.getEmail());
        safetyUser.setPhone(originalUser.getPhone());
        safetyUser.setUserRole(originalUser.getUserRole());
        safetyUser.setUserStatus(originalUser.getUserStatus());
        safetyUser.setCreateTime(originalUser.getCreateTime());
        safetyUser.setPlanetCode(originalUser.getPlanetCode());
        return safetyUser;
    }
    private boolean isAdmin(HttpServletRequest request){
        //鉴权
        Object obj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        User user=(User)obj;
        if(user==null||user.getUserRole()!=UserConstant.ADMIN_ROLE){
            return false;
        }
        return true;
    }
}




